package com.physics.mps.module.task.sub;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.physics.mps.common.util.AssertUtil;
import com.physics.mps.common.util.LoginUtil;
import com.physics.mps.entity.dto.*;
import com.physics.mps.entity.dto.*;
import com.physics.mps.entity.enums.CodeEnum;
import com.physics.mps.entity.enums.ScriptStatusEnum;
import com.physics.mps.entity.vo.SubTaskQueryVo;
import com.physics.mps.entity.vo.SubTaskVo;
import com.physics.mps.mapper.SubTaskMapper;
import com.physics.mps.module.compute.TaskComputeResultService;
import com.physics.mps.module.setting.AppEntityService;
import com.physics.mps.module.setting.AppMoluleService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author mcsoft
 * @date 2023/9/15 10:01
 * @description 子任务接口实现
 */
@RequiredArgsConstructor
@Slf4j
@Service
public class SubTaskServiceImpl extends ServiceImpl<SubTaskMapper, SubTaskEntity> implements SubTaskService {

    private final SubTaskMapper subTaskMapper;

    private final AppEntityService appEntityService;

    private final AppMoluleService appMoluleService;

    private final TaskComputeResultService taskComputeResultService;

    private final ExecutorService executeScriptExecutorService;


    @Override
    public Page<SubTaskEntity> selectTask(int current, int size, SubTaskQueryVo vo) {
        vo.setUserId(Objects.requireNonNull(LoginUtil.getUserId()).toString());
        Page<SubTaskEntity> pageList = subTaskMapper.selectTask(new Page<>(current, size), vo);
        List<SubTaskEntity> records = pageList.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            records.forEach(record -> {
                LocalDateTime createTime = record.getCreateTime();
                if (null != createTime) {
                    String format = DateUtil.format(createTime, DatePattern.CHINESE_DATE_TIME_PATTERN);
                    record.setCreateTimeStr(format);
                }
                LocalDateTime updateTime = record.getUpdateTime();
                if (null != updateTime) {
                    String format = DateUtil.format(updateTime, DatePattern.CHINESE_DATE_TIME_PATTERN);
                    record.setUpdateTimeStr(format);
                }
            });
        }
        pageList.setRecords(records);
        return pageList;
    }

    @Override
    public Page<SubTaskEntity> selectFastCAETask(int current, int size, SubTaskQueryVo vo) {
        vo.setUserId(Objects.requireNonNull(LoginUtil.getUserId()).toString());
        Page<SubTaskEntity> pageList = subTaskMapper.selectFastCAETask(new Page<>(current, size), vo);
        List<SubTaskEntity> records = pageList.getRecords();
        if (CollectionUtil.isNotEmpty(records)) {
            records.forEach(record -> {
                LocalDateTime createTime = record.getCreateTime();
                if (null != createTime) {
                    String format = DateUtil.format(createTime, DatePattern.CHINESE_DATE_TIME_PATTERN);
                    record.setCreateTimeStr(format);
                }
                LocalDateTime updateTime = record.getUpdateTime();
                if (null != updateTime) {
                    String format = DateUtil.format(updateTime, DatePattern.CHINESE_DATE_TIME_PATTERN);
                    record.setUpdateTimeStr(format);
                }
            });
        }
        pageList.setRecords(records);
        return pageList;
    }

    @Override
    public void deleteSubTask(String id) {
        removeById(id);
    }

    @Override
    public String subTaskFileUrl(String id) {
        SubTaskEntity subTask = getSubTask(id);
        // TODO
        return subTask.getFilePath();
    }

    @Override
    public SubTaskEntity getSubTask(String id) {
        SubTaskEntity subTaskEntity = getById(id);
        AssertUtil.isNull(subTaskEntity, CodeEnum.SUB_TASK_NOT_EXIST);
        AppEntity appEntity = appEntityService.getById(subTaskEntity.getAppId());
        AppModuleEntity appModuleEntity = appMoluleService.getById(subTaskEntity.getModuleId());
        subTaskEntity.setAppName(appEntity.getAppName());
        subTaskEntity.setAppModuleName(appModuleEntity.getName());
        return subTaskEntity;
    }


    @Override
    public String addSubTask(String appId, String moduleId, String taskId, String taskName, String filePath) {
        SubTaskEntity subTask = new SubTaskEntity();
        subTask.setId(IdUtil.fastSimpleUUID());
        subTask.setName(taskName);
//        subTask.setStatus(ScriptStatusEnum.QUEUE.getStatus());
        subTask.setUserId(Objects.requireNonNull(LoginUtil.getUserId()).toString());
        subTask.setTaskId(taskId);
        subTask.setAppId(appId);
        subTask.setModuleId(moduleId);
        save(subTask);
        return subTask.getId();
    }


    @Override
    public void updateTask(String subTaskId, String logFilePath, String resultFilePath, String resultImgPath, String url, String picUrl, String jsonUrl) {
        SubTaskEntity subTask = new SubTaskEntity();
        subTask.setId(subTaskId);
        subTask.setStatus(ScriptStatusEnum.COMPLETE.getStatus());
        // 生成结果记录
        TaskComputeResultEntity taskComputeResultEntity = new TaskComputeResultEntity();
        // 用子任务的主键
        taskComputeResultEntity.setId(subTaskId);
        taskComputeResultEntity.setFilePath(resultFilePath);
        taskComputeResultEntity.setPicPath(resultImgPath);
        taskComputeResultEntity.setResultUrl(url);
        taskComputeResultEntity.setPicUrl(picUrl);
        taskComputeResultEntity.setJsonUrl(jsonUrl);
        taskComputeResultService.save(taskComputeResultEntity);
        subTask.setComputeResultId(subTaskId);

//        if(FileUtil.exist(logFilePath)){
//            // 读取logFilePath内容
//            String log = FileUtil.readUtf8String(logFilePath);
//            // 判断log内容，不能超过5000
//            if(StrUtil.isNotEmpty(log) && log.length() > 5000){
//                log = log.substring(0, 5000);
//            }
//            subTask.setCmdLog(log);
//        }
        subTask.setLogPath(logFilePath);
        updateById(subTask);
    }

    @Override
    public List<StatusCount> getNumber() {
        return subTaskMapper.getNumber(LoginUtil.getUserId().toString());
    }

    @Override
    public List<StatusCount> getFastCAENumber() {
        return subTaskMapper.getFastCAENumber(LoginUtil.getUserId().toString());
    }

    @Override
    public Map<String, Object> getThreadPoolStatus() {
        ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executeScriptExecutorService;
        JSONObject entries = new JSONObject();
        BlockingQueue<Runnable> queue = threadPoolExecutor.getQueue();
        entries.set("active", threadPoolExecutor.getActiveCount());
        entries.set("queue", queue.size());

        return entries;
    }

    @Override
    public String increase(SubTaskVo subTaskVo) {
        SubTaskEntity subTask = new SubTaskEntity();
        subTask.setName(subTaskVo.getTaskName() + "-" + IdUtil.simpleUUID());
        subTask.setStatus(ScriptStatusEnum.INIT.getStatus());
        subTask.setUserId(Objects.requireNonNull(LoginUtil.getUserId()).toString());
        subTask.setTaskId(IdUtil.fastSimpleUUID());
        subTask.setAppId(subTaskVo.getAppId());
        subTask.setModuleId(subTaskVo.getAppModuleId());
        save(subTask);
        return subTask.getId();
    }
}
